﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace lifeofbob
{

#region Enum

    enum RWeapon
    {  
        Rock,
        Blowgun,
        Shuriken,
        Throwingknife,
        Bow,
        Spear,
        Crossbow
    }

    enum MWeapon
    { 
        Stick,
        Dagger,
        Gauntlet,
        Axe,
        Maxe,
        Sword,
        Flail,
        Spear,
        Greathammer
    }

    enum Weapon
    { 
        Melee,
        Range,
        None
    }
    #endregion

    public class Player
    {

    #region Variabler

        double elapsedTime;
        private Texture2D _texture;
        private Rectangle _rect;
        private GamePadState gpState_new;
        private GamePadState gpState_old;

        //Värden för spelaren
        private Vector2 direction;
        private float rotation;
        private float maxSpeed = 2;
        private float playerX;
        private float playerY;
        public Vector2 player_center;
        private bool charged = false;
        private double shootTime = 0;
        private double shootCd = 0.1;

        private List<Projectile> projectile_list = new List<Projectile>();

        //Enum för melee och range vapen
        private MWeapon m_weapon;
        private RWeapon r_weapon;
        private Weapon weapon;

#endregion

    #region Konstruktor
        public Player() 
        {
            texture = TextureLibrary.player;
            _rect = new Rectangle(400, 400, 32, 32);
            playerX = 400;
            playerY = 400;
            m_weapon = MWeapon.Stick;
            r_weapon = RWeapon.Rock;
            weapon = Weapon.Range;

        }
#endregion

    #region Updateringsmetoder
        /// <summary>
        /// Generell updaterings metod
        /// </summary>
        /// <param name="gt">Gametime</param>
        public void Update(GameTime gt) 
        {
            gpState_new = GamePad.GetState(PlayerIndex.One, GamePadDeadZone.Circular);

            GamePad.SetVibration(PlayerIndex.One, 0.0f, 0.0f);
            
            //Uppdaterar spelaren
            UpdatePlayer();

            //Uppdaterar vapen
            UpdateWeapon(gt);

            //Uppdaterar projektiler och skapar även nya
            UpdateProjectile(gt);

            //Vibrationer till kontrollern
            gpState_old = gpState_new;
        }

        /// <summary>
        /// Updaterar spelaren
        /// </summary>
        private void UpdatePlayer()
        {
            //Hämtar värdena (-1 - 1) för högra kontrollspaken
            direction = gpState_new.ThumbSticks.Right;

            //Rör spelaren beroende på hur du rör din spak
            playerX += gpState_new.ThumbSticks.Left.X * maxSpeed;
            playerY -= gpState_new.ThumbSticks.Left.Y * maxSpeed;

            //Hämtar center positionen för spelaren
            player_center.X = playerX;
            player_center.Y = playerY;

            //Räknar ut vinklen som spelaren siktar mot såvidare spaken inte är i mitten
            rotation = (float)Math.Atan2(direction.Y, direction.X);
        }

        /// <summary>
        /// Updaterar projektiler
        /// </summary>
        /// <param name="gt">Gametime</param>
        private void UpdateProjectile(GameTime gt)
        {         
            //Testar ifall spelaren skjuter eller inte
            Shoot(gt);
            //Testar ifall spelaren gör ultimate eller inte
            Ultimate(gt);
            //Uppdaterar alla projektiler i listan
            for (int i = 0; i < projectile_list.Count; i++)
            {
                if (projectile_list[i].OutOfBounds(player_center) || projectile_list[i].OutOfTime())
                    projectile_list.RemoveAt(i);
                else
                    projectile_list[i].Update(gt);
            }
        }

        /// <summary>
        /// Updaterar vapnen
        /// </summary>
        private void UpdateWeapon(GameTime gt)
        {
            
            if (gpState_new.Buttons.X == ButtonState.Pressed && gpState_old.Buttons.X == ButtonState.Released)
            {
                if (weapon == Weapon.Melee)
                    weapon = Weapon.Range;
                else if (weapon == Weapon.Range)
                    weapon = Weapon.Melee;
            }

            if (gpState_new.Buttons.Y == ButtonState.Pressed && gpState_old.Buttons.Y == ButtonState.Released && weapon == Weapon.Range)
            {
                if (r_weapon == RWeapon.Rock)
                {
                    r_weapon = RWeapon.Shuriken;
                }
                else
                    r_weapon = RWeapon.Rock;
            }

        }
#endregion

    #region Drawmetoder
        /// <summary>
        /// Draw metod för spelaren och projektilerna
        /// </summary>
        /// <param name="sb">Spritebatch</param>
        public void Draw(SpriteBatch sb)
        {
            sb.Draw(texture, new Rectangle((int)playerX, (int)playerY, 32, 32), null, Color.White, -rotation, new Vector2(16, 16), SpriteEffects.None, 0);
            for(int i = 0; i < projectile_list.Count; i++)
            {
                projectile_list[i].Draw(sb);
            }
        }
#endregion

    #region Misc metoder

        private void Ultimate(GameTime gt)
        {
            if (gpState_new.Triggers.Left == 1 && !charged)
                elapsedTime += gt.ElapsedGameTime.TotalSeconds;
            if (elapsedTime >= 1)
            {
                charged = true;
                elapsedTime = 0;
            }

            if (gpState_new.Triggers.Left == 0 && charged)
            {
                UltimateShuriken();
                charged = false;
            }
        }
        /// <summary>
        /// Method for controling shooting
        /// </summary>
        /// <param name="gt"></param>
        private void Shoot(GameTime gt)
        {
            if (gpState_new.Triggers.Right == 1)
                shootTime += gt.ElapsedGameTime.TotalSeconds;
            
            if (shootTime >= shootCd)
            {
                //Bestämmer vad vi ska göra beroende på vilket vapen vi har
                switch (r_weapon)
                {
                    case RWeapon.Rock:
                        {
                            projectile_list.Add(new Rock(player_center, new Vector2(direction.X * 4, -direction.Y * 4)));
                            break;
                        }
                    case RWeapon.Shuriken:
                        {
                            projectile_list.Add(new Shuriken(player_center, new Vector2(direction.X * 4, -direction.Y * 4)));
                            break;
                        }
                }
                shootTime = 0;
            }
        }
        /// <summary>
        /// Ultimate for shuriken
        /// </summary>
        private void UltimateShuriken()
        {
            projectile_list.Add(new Shuriken(player_center, new Vector2(4, 4), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(4, -4), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(-4, 4), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(0, 4), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(4, 0), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(-4, 0), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(0, -4), 20));
            projectile_list.Add(new Shuriken(player_center, new Vector2(-4, -4), 20));
        }
        #endregion

    #region Properties
        /// <summary>
        /// Rectangle property
        /// </summary>
        public Rectangle rectangle
        {
            get { return _rect; }
            set { _rect = value;}
        }
        /// <summary>
        /// Texture property
        /// </summary>
        public Texture2D texture
        {
            get { return _texture; }
            set { _texture = value; }
        }

        public Vector2 center
        {
            get { return player_center; }
        }
        #endregion 
    }
}
